import chalk from "chalk"
import * as glob from "glob"
import dayjs from "dayjs"
import pRetry from "p-retry"
import schedule from "node-schedule"

import { biliTrace, biliSend } from "@/services"
import { clearHistory } from "@/methods"
import { useNode } from "@/hooks"

import dutyJson from "env.duty.json"

const { path, fs } = useNode()

import { desktopPath, setIp, killChrome, resetMasterIp } from "@/utils"

const main = async () => {
  console.log(chalk.yellow("切回主ip"))

  await resetMasterIp()

  // 清除超过2天的发送历史
  clearHistory()

  const YTD = dayjs().format("YYYY-MM-DD")

  const ipMap = dutyJson.ipMap

  const folderIpMap = Object.fromEntries(
    ipMap.map(({ folder, ip }) => [folder, ip]),
  )

  const folders = [...new Set(ipMap.map(i => i.folder))]

  /**根据时间挑选合适的任务 */
  const tasks = dutyJson.tasks
    .map(i => {
      const { time, folder } = i

      const ip = folderIpMap[folder]

      const date = `${YTD} ${time}`

      return { ...i, date, ip }
    })
    .filter(({ date }) => dayjs().isBefore(date))

  const courseMap = folders.map(folder => {
    const options = { windowsPathsNoEscape: true }

    const biliCourse = glob.sync(
      path.join(desktopPath, `t_${folder}/*/bili/`),
      options,
    )

    return [folder, biliCourse]
  })

  const biliCourseStore = Object.fromEntries(courseMap)

  const historyBackupPath = `Desktop/history/${YTD}`

  for (const task of tasks) {
    const { folder, date, ip } = task

    const allBiliCourse = biliCourseStore[folder]

    if (!allBiliCourse.length) {
      console.log(chalk.yellow(folder, "目录请填补资料"))
      continue
    }

    const [biliCoursePath] = allBiliCourse.splice(0, 1)

    const job = schedule.scheduleJob(
      new Date(date),

      async function (ip: string, biliCoursePath: string) {
        await killChrome().catch(biliTrace.error)

        console.info(`切换ip到:`, ip)
        await setIp(ip)

        await pRetry(() => biliSend(biliCoursePath, ip), {
          onFailedAttempt: async error => {
            await killChrome().catch(e => e)

            const { attemptNumber } = error
            biliTrace.error("\r\n", "❌❌❌❌❌❌❌❌❌❌❌❌")
            biliTrace.error(`重试 ${attemptNumber} 次，错误详情如下：`)
            biliTrace.error(biliCoursePath, ip)
            biliTrace.error(error.message)
            biliTrace.error("\r\n", "❌❌❌❌❌❌❌❌❌❌❌❌")
          },

          retries: 2,

          maxTimeout: 1000 * 60 * 10,
        })
          .then(async () => {
            const courseDir = path.dirname(biliCoursePath)

            const historyPath = courseDir.replace("Desktop", historyBackupPath)

            fs.ensureDirSync(historyBackupPath)

            fs.moveSync(courseDir, historyPath, { overwrite: true })

            console.log(chalk.green("将", biliCoursePath, "移到history目录"))
          })
          .finally(async () => {
            await killChrome().catch(e => e)

            console.info("切回主ip")
            await resetMasterIp()
            job.cancel()
          })
      }.bind(null, ip, biliCoursePath),
    )
  }

  const realTime = dayjs().format("YYYY-MM-DD HH:mm:ss")

  console.log(chalk.blue("\n", "任务初始化成功：", realTime))

  console.table(tasks)
}

// 创建一个每天凌晨1点触发的规则
schedule.scheduleJob({ hour: 1, minute: 15, second: 0 }, main)

main()
